﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.Experimental.UIElements;
using UnityEngine;
using UnityEngine.UI;

public class MyEditor : EditorWindow
{
    private List<ToggleData> _toggleDatas;
    private GameObject curSelectGo;
    private string titleTxt;
    private string[] compTypeArr = new[] {"Text", "Image", "Button", "Toggle", "Slider", "InputField", "Transform"};
    private string[] windowTypeArr = new[] {"Normal", "Fixed", "Popup"};
    private string[] AnimionTypeArr = new[] {"Drop", "LeftOut", "RightOut", "CenterScale"};
    private ClassData _classData;

    private Dictionary<string, ToggleData> _dictionary;

    private List<string> tweenOptions = new List<string>();
    private int tweenIndex = 0;
    private string tweenObjectName = "";

    private Vector2 scroPos;
    private string createPath = "Assets/Script/UI";

    [MenuItem("工具/脚本生成")]
    static void Init()
    {
        GetWindow<MyEditor>().titleContent = new GUIContent("TTUI脚本生成",Resources.Load<Texture>("Icon/eg"));
    }

    private void OnGUI()
    {
        scroPos = GUILayout.BeginScrollView(scroPos, GUILayout.Width(position.width),
            GUILayout.Height(position.height));
        GUILayout.Label(titleTxt);
        if (_toggleDatas != null)
        {
            ShowToggle(_toggleDatas);


            GUILayout.Label("\n================================================================\n");
            GUILayout.Label("WindowType");
            _classData.wtype =
                (WindowType) GUILayout.SelectionGrid((int) _classData.wtype, windowTypeArr, windowTypeArr.Length);


            ShowTweenPopup();


            GUILayout.Label("AnimationType");
            _classData.anim =
                (Anim) GUILayout.SelectionGrid((int) _classData.anim, AnimionTypeArr, AnimionTypeArr.Length);


            GUILayout.Label("\n================================================================\n");
            GUILayout.Label("生成位置:");
            createPath = GUILayout.TextField(createPath);
            if (GUILayout.Button("生成"))
            {
                if (!Directory.Exists(createPath))
                {
                    Directory.CreateDirectory(createPath);
                    AssetDatabase.Refresh();
                }

                GenerateCode();
            }
        }


        GUILayout.EndScrollView();
    }

    private void GenerateCode()
    {
        List<ToggleData> temp = new List<ToggleData>();
        GetToggleData(_toggleDatas, temp);
        foreach (var toggleData in temp)
        {
            if (toggleData.isSelect)
            {
                string pro = "private " + toggleData.ctype + " " + toggleData.name + ";";
                _classData.propertys.Add(pro);

                string awa = toggleData.name + " = go.transform.Find(\"" + toggleData.path + "\")";
                if (toggleData.ctype != CompType.Transform)
                {
                    awa += ".GetComponent<" + toggleData.ctype + ">();";
                }
                else
                {
                    awa += ";";
                }

                _classData.awakes.Add(awa);

                if (toggleData.ctype == CompType.Button)
                {
                    string btnAdd = toggleData.name + ".onClick.AddListener(" + toggleData.name + "Click);";
                    _classData.awakes.Add(btnAdd);

                    string btnClick = "private void " + toggleData.name + "Click()\n    {\n\n    }";
                    _classData.btnEvents.Add(btnClick);
                }
            }
        }

        string classDataStr = "using System.Collections;\n" +
                              "using System.Collections.Generic;\n" +
                              "using TinyTeam.UI;\n" +
                              "using DG.Tweening;\n" +
                              "using UnityEngine;\n" +
                              "using UnityEngine.UI;\n\n" +
                              "public class " + curSelectGo.name + " : TTUIPage\n" +
                              "{\n";

        foreach (var classDataProperty in _classData.propertys)
        {
            classDataStr += "    " + classDataProperty + "\n";
        }

        classDataStr += "    public " + curSelectGo.name + "() : base(UIType." + _classData.wtype +
                        ", UIMode.DoNothing, UICollider.None)\n" +
                        "    {\n" +
                        "        uiPath = \"UI/" + curSelectGo.name + "\";\n" +
                        "    }\n\n";
        classDataStr += "    public override void Awake(GameObject go)\n" +
                        "    {\n";

        foreach (var classDataAwake in _classData.awakes)
        {
            classDataStr += "        " + classDataAwake + "\n";
        }

        classDataStr += "    }\n";

        classDataStr += "    public override void Refresh()\n" +
                        "    {\n\n" +
                        "    }\n\n";

        string animData = GetAnimData(_classData.anim);

        classDataStr += animData;


        foreach (var classDataBtnEvent in _classData.btnEvents)
        {
            classDataStr += classDataBtnEvent + "\n\n";
        }

        classDataStr += "}";

        if (File.Exists(Path.Combine(createPath, curSelectGo.name + ".cs")))
        {
            Debug.LogError("文件【" + Path.Combine(createPath, curSelectGo.name) + "】已存在！无法生成！");
        }
        else
        {
            FileInfo fileInfo = new FileInfo(Path.Combine(createPath, curSelectGo.name + ".cs"));
            StreamWriter streamWriter = fileInfo.CreateText();
            streamWriter.WriteLine(classDataStr);
            streamWriter.Close();
            AssetDatabase.Refresh();
        }
    }

    private string GetAnimData(Anim anim)
    {
        string data = Resources.Load<TextAsset>("AnimTxt/" + anim).text;
        data = data.Replace("__obj", tweenObjectName);
        return data;
    }

    private void ShowTweenPopup()
    {
        if (_toggleDatas != null && _toggleDatas.Count > 0)
        {
            List<ToggleData> temp = new List<ToggleData>();
            tweenOptions.Clear();
            GetToggleData(_toggleDatas, temp);
            tweenOptions.Add("gameObject");
            foreach (var toggleData in temp)
            {
                tweenOptions.Add(toggleData.path);
            }


            GUILayout.Label("");
            GUILayout.Label("===================================================");
            GUILayout.Label("请选择动画作用对象");
            if (tweenIndex >= tweenOptions.Count - 1)
            {
                tweenIndex = 0;
            }

            tweenIndex = EditorGUILayout.Popup(tweenIndex, tweenOptions.ToArray());
            tweenObjectName = tweenIndex == 0 ? "gameObject" : temp[tweenIndex - 1].name;
        }
    }

    private void GetToggleData(List<ToggleData> toggleDatas, List<ToggleData> outToggleDatas)
    {
        foreach (var toggleData in toggleDatas)
        {
            outToggleDatas.Add(toggleData);
            GetToggleData(toggleData.child, outToggleDatas);
        }
    }

    private void GetToggleData(List<ToggleData> toggleDatas, GameObject root, string parentPath = "")
    {
        foreach (Transform tr in root.transform)
        {
            string tempPath = parentPath == "" ? "" : parentPath + "/";
            string thisPath = tempPath + tr.name;
            string proName = GetName(tr.name.Replace("(", "").Replace(")", "").Replace(" ", ""));
            ToggleData thisData = new ToggleData
            {
                isSelect = true,
                path = thisPath,
                child = new List<ToggleData>(),
                name = proName
            };


            _dictionary.Add(proName, thisData);

            if (tr.GetComponent<Button>() != null)
            {
                thisData.ctype = CompType.Button;
            }
            else if (tr.GetComponent<InputField>() != null)
            {
                thisData.ctype = CompType.InputField;
            }
            else if (tr.GetComponent<Slider>() != null)
            {
                thisData.ctype = CompType.Slider;
            }
            else if (tr.GetComponent<Toggle>() != null)
            {
                thisData.ctype = CompType.Toggle;
            }
            else if (tr.GetComponent<Text>() != null)
            {
                thisData.ctype = CompType.Text;
            }
            else if (tr.GetComponent<Image>() != null)
            {
                thisData.ctype = CompType.Image;
            }
            else
            {
                thisData.ctype = CompType.Transform;
            }

            if ((thisData.ctype != CompType.Button && tr.GetComponentInParent<Button>() != null) ||
                (thisData.ctype != CompType.Slider && tr.GetComponentInParent<Slider>() != null) ||
                (thisData.ctype != CompType.InputField && tr.GetComponentInParent<InputField>() != null) ||
                (thisData.ctype != CompType.Toggle && tr.GetComponentInParent<Toggle>() != null))
            {
                thisData.isSelect = false;
            }


            toggleDatas.Add(thisData);
            GetToggleData(thisData.child, tr.gameObject, thisPath);
        }
    }

    private void ShowToggle(List<ToggleData> toggleDatas)
    {
        foreach (var toggleData in toggleDatas)
        {
            toggleData.isSelect = GUILayout.Toggle(toggleData.isSelect, toggleData.path);
            toggleData.ctype =
                (CompType) GUILayout.SelectionGrid((int) toggleData.ctype, compTypeArr, compTypeArr.Length);
            ShowToggle(toggleData.child);
        }
    }

    private string GetName(string name)
    {
        string temp = name;
        int n = 1;
        while (true)
        {
            if (_dictionary.ContainsKey(temp))
            {
                temp = name + n;
                n++;
            }
            else
            {
                break;
            }
        }

        return temp;
    }

    private void OnSelectionChange()
    {
        if (curSelectGo != Selection.activeGameObject)
        {
            curSelectGo = null;
            _toggleDatas = null;
            _classData = null;
            _dictionary = null;
            tweenOptions.Clear();
        }

        if (Selection.activeGameObject != null && Selection.activeGameObject != curSelectGo)
        {
            curSelectGo = Selection.activeGameObject;
            _toggleDatas = new List<ToggleData>();
            _classData = new ClassData();
            _dictionary = new Dictionary<string, ToggleData>();
            GetToggleData(_toggleDatas, curSelectGo);
        }

        if (_toggleDatas == null)
        {
            titleTxt = "请先选择一个预制体";
        }
        else if (curSelectGo != null)
        {
            titleTxt = "以下是UI预制体" + curSelectGo.name +
                       "子物体选项\n================================================================";
        }
    }

    private void OnInspectorUpdate()
    {
        Repaint();
        OnSelectionChange();
    }
}

public class ToggleData
{
    public string name;
    public bool isSelect;
    public string path;
    public List<ToggleData> child;
    public CompType ctype;
}

public enum CompType
{
    Text,
    Image,
    Button,
    Toggle,
    Slider,
    InputField,
    Transform
}

public class ClassData
{
    public List<string> propertys;
    public List<string> awakes;
    public List<string> btnEvents;
    public WindowType wtype;
    public Anim anim;

    public ClassData()
    {
        propertys = new List<string>();
        awakes = new List<string>();
        btnEvents = new List<string>();
    }
}

public enum WindowType
{
    Normal,
    Fixed,
    PopUp
}

public enum Anim
{
    Drop,
    LeftOut,
    RightOut,
    CenterScale
}